using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using System.IO;

namespace LetsGoToSchool
{
    /// <summary>
    /// Interaction logic for Doodle.xaml
    /// </summary>
    public partial class Doodle : SurfaceWindow
    {
        private Stack<DoodleStatNode> _doodleStats = new Stack<DoodleStatNode>();
        private DoodleStatNode _currStatNode;

        /// <summary>
        /// Default constructor.
        /// </summary>
        public Doodle()
        {
            InitializeComponent();

            // Add handlers for Application activation events
            AddActivationHandlers();
            _selection.setMain(this);
            _palette.setDrawingCanvas(_drawingCanvas);
            Contacts.AddPreviewContactDownHandler(_mainCanvas, AdjustPalette);
        }

        /// <summary>
        /// static methid to get the icon for the game, same for all the games
        /// </summary>
        /// <returns></returns>
        public static String getIconFileName()
        {
            return "Icon-Doodle.png";
        }

        /// <summary>
        /// set the background using the given image if it is an image, set it to white otherwise
        /// </summary>
        /// <param name="img"></param>
        public void setBackground(DoodleImage img)
        {
            if (img.Content is Image)
            {
                Image image = img.Content as Image;
                ImageBrush brush = new ImageBrush(image.Source);
                //scale the image down, if the image is bigger than the canvas; otherwise the image stays unchanged
                if (image.Source.Height >= _drawingCanvas.Height || image.Source.Width >= _drawingCanvas.Width)
                {
                    brush.Stretch = Stretch.Uniform;
                }
                else
                {
                    brush.Stretch = Stretch.None;
                }
                _drawingCanvas.Background = brush;
            }
            else
            {
                _drawingCanvas.Background = new SolidColorBrush(Colors.White);
            }
        }

        /// <summary>
        /// initial setup for each game session
        /// </summary>
        public void startGame() 
        {
            _mainCanvas.Visibility = Visibility.Visible;
            //open a new session node and store the start time
            _currStatNode = new DoodleStatNode(DateTime.Now);
        }

        /// <summary>
        /// store the session data to database
        /// </summary>
        public void reportResults() 
        {
            foreach (DoodleStatNode node in _doodleStats)
            {
                node.storeToDatabase();
            }
        }

        private void _quitButton_Click(object sender, RoutedEventArgs e)
        {
            //store the end time and close the session node(puch it to the stack)
            _currStatNode.EndTime = DateTime.Now;
            _doodleStats.Push(_currStatNode);
            _currStatNode = null;
            this.Close();
        }

        /// <summary>
        /// end the corrent session and go back to image selection mode
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _restarteButton_Click(object sender, RoutedEventArgs e)
        {
            _currStatNode.EndTime = DateTime.Now;
            _doodleStats.Push(_currStatNode);
            _currStatNode = null;
            _mainCanvas.Visibility = Visibility.Hidden;
            _drawingCanvas.Strokes.Clear();
            _selection.Visibility = Visibility.Visible;
        }

        private void _helpButton_Click(object sender, RoutedEventArgs e)
        {
            NoContactCanvas.Visibility = Visibility.Visible;
            //I didn't check in the video, just comment the line out
            _helpBox.playMovie("C:/lgts-Images/kung-fu-panda-trailer.mpg");
        }

        private void _saveButton_Click(object sender, RoutedEventArgs e)
        {
            //save the drawing canvas to image
            Rect bounds = VisualTreeHelper.GetDescendantBounds(_drawingCanvas);
            RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Pbgra32);
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(_drawingCanvas);
                dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }
            rtb.Render(dv);

            PngBitmapEncoder png = new PngBitmapEncoder();
            png.Frames.Add(BitmapFrame.Create(rtb));

            //use the corrent time as file name, swap out any special 
            //characters that can't be recognized by the database
            string now = DateTime.Now.ToString();
            now = now.Replace('/', '-');
            now = now.Replace(':', '-');
            now = now.Replace(' ', '-');
            string path = "C:/lgts-Images/" + now + ".png";
            FileStream file = new FileStream(path, FileMode.Create);
            png.Save(file);
            file.Close();

            Database.addImage(path, "MyWork");

            //show the "saved" message for 2 seconds for notifying
            _saved.Visibility = Visibility.Visible;
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(2);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            (sender as DispatcherTimer).Stop();
            _saved.Visibility = Visibility.Hidden;
        }

        /// <summary>
        /// make the paletta follow the user
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AdjustPalette(object sender, ContactEventArgs e)
        {
            Rect rect = e.Contact.BoundingRect;
            if (rect.Bottom - rect.Top > 50 || rect.Right - rect.Left > 50)
            {
                _paletteSVI.Center = new Point((rect.Right + rect.Left) / 2, rect.Top - 150);
            }
        }

        /// <summary>
        /// Occurs when the window is about to close. 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            this.reportResults();
            // Remove handlers for Application activation events
            RemoveActivationHandlers();
        }

        /// <summary>
        /// Adds handlers for Application activation events.
        /// </summary>
        private void AddActivationHandlers()
        {
            // Subscribe to surface application activation events
            ApplicationLauncher.ApplicationActivated += OnApplicationActivated;
            ApplicationLauncher.ApplicationPreviewed += OnApplicationPreviewed;
            ApplicationLauncher.ApplicationDeactivated += OnApplicationDeactivated;
        }

        /// <summary>
        /// Removes handlers for Application activation events.
        /// </summary>
        private void RemoveActivationHandlers()
        {
            // Unsubscribe from surface application activation events
            ApplicationLauncher.ApplicationActivated -= OnApplicationActivated;
            ApplicationLauncher.ApplicationPreviewed -= OnApplicationPreviewed;
            ApplicationLauncher.ApplicationDeactivated -= OnApplicationDeactivated;
        }

        /// <summary>
        /// This is called when application has been activated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationActivated(object sender, EventArgs e)
        {
            //TODO: enable audio, animations here
        }

        /// <summary>
        /// This is called when application is in preview mode.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationPreviewed(object sender, EventArgs e)
        {
            //TODO: Disable audio here if it is enabled

            //TODO: optionally enable animations here
        }

        /// <summary>
        ///  This is called when application has been deactivated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationDeactivated(object sender, EventArgs e)
        {
            //TODO: disable audio, animations here
        }
    }

    /// <summary>
    /// session node that stores the games stats
    /// </summary>
    public class DoodleStatNode : GameStatNode
    {
        public DoodleStatNode(DateTime startTime)
        {
            _startTime = startTime;
        }

        private DateTime _startTime;
        private DateTime _endTime;
        public DateTime StartTime { get { return _startTime; } }
        public DateTime EndTime { get { return _endTime; } set { _endTime = value; } }
        //returns the seesion length
        public TimeSpan getDuration()
        {
            if (_endTime == null)
            {
                _endTime = DateTime.Now;
            }
            return _endTime.Subtract(_startTime);
        }

        public void storeToDatabase()
        {
            Database.writeDoodleSessionData(this);
        }
    }
}